﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using VentaElectrodomesticos.Negocio;
using VentaElectrodomesticos.Datos;
using VentaElectrodomesticos.Contrato;

namespace VentaElectrodomesticos.GUI.Base
{
    public partial class BaseListado<T,X,W,Z> : BaseValidaciones, IBaseListado
        where X : BaseEdicion<T, W, Z>, new()
        where T : BaseNegocio<W, Z>, new() 
        where W : BaseDAO<Z>, new() 
        where Z : Entity, new()
    {
        public T Negocio { get; set; }
        public X FormEdicion { get; set; }
        public Z Entity { get; set; }

        private bool isSearchForm = false;        
        

        protected virtual DataGridView DgList { get; set; }
        protected virtual void initForm(X form) { }
        protected virtual void initTable(DataGridView table) { }
        protected virtual Z getFilter() { return null; }

        private String SELECCIONAR = "Editar";
        private String BORRAR = "Dar de baja";

        public BaseListado()
        {
            InitializeComponent();
        }        

        public bool IsSearchForm 
        {
            get { 
                return this.isSearchForm;
            }
            set {
                this.isSearchForm = value;
                if (this.isSearchForm)
                    this.initializeSearch();
            }
        }

        private void BaseListado_Load(object sender, EventArgs e)
        {
            this.setGridDefaultProperties();
            this.initialize();            
        }

        private void setGridDefaultProperties()
        {
            this.DgList.CellClick += new DataGridViewCellEventHandler(DgList_CellClick);
            this.DgList.AllowUserToAddRows = false;
            this.DgList.AllowUserToDeleteRows = false;
            this.DgList.EditMode = DataGridViewEditMode.EditProgrammatically;
            this.DgList.RowHeadersWidth = 24;
        }

        private void initializeSearch()
        {
            this.btNew.Visible = false;
            this.SELECCIONAR = "Seleccionar";
            this.toolStripSeparator2.Visible = false;
        }

        protected virtual void initialize()
        {
            this.Negocio = new T();
            this.Entity = new Z();
            this.DgList.Columns.Clear();
            try {
                this.setList(getObjectList());

                if (!this.isSearchForm)
                {
                    this.addNewButtonColumn(this.BORRAR);
                }
                this.addNewButtonColumn(this.SELECCIONAR);
                this.DgList.Columns["Id"].Visible = false;
                this.initTable(this.DgList);
            }
            catch (NegocioException ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (DatosException ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (Exception)
            {
                MessageBox.Show("Error inesperado. Ponganse en contacto con el administrador del sistema ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }         
        }

        private void addNewButtonColumn(String name)
        {
            DataGridViewButtonColumn dataGridViewButtonColumn = new DataGridViewButtonColumn();
            dataGridViewButtonColumn.Text = name;
            dataGridViewButtonColumn.Name = name;
            dataGridViewButtonColumn.Tag = true;
            dataGridViewButtonColumn.UseColumnTextForButtonValue = true;
            this.DgList.Columns.Add(dataGridViewButtonColumn);            
        }

        protected virtual List<Z> getObjectList() {
            return this.Negocio.getAll();
        }

        protected void setList(List<Z> list)
        {
            BindingSource bindingSource = new BindingSource();
            bindingSource.DataSource = list;
            this.DgList.DataSource = bindingSource;

            if (this.DgList.Columns.Contains("inactivo"))
            {
                if (this.isSearchForm)
                {
                    this.DgList.Columns["inactivo"].Visible = false;                    
                }
                else {
                    this.DgList.Columns["inactivo"].HeaderText = "Dado de baja";
                }
            }
        }

        protected void delete(int id) 
        {            
            this.Entity.Id = id;
            this.Negocio.delete(this.Entity);
            MessageBox.Show("Dado de baja correcto", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
            this.doFilter();
        }

        private void beginEdit(bool edit)
        {
            this.FormEdicion = new X();
            this.FormEdicion.changeLayout(edit);
            this.initForm(this.FormEdicion);
            this.FormEdicion.Entity = this.Entity;
            this.FormEdicion.ShowInTaskbar = false;
            this.FormEdicion.Tag = this;
            if (DialogResult.OK == this.FormEdicion.ShowDialog(this))
                this.initialize();
        }

        protected void edit(int id)
        {
            this.Entity.Id = id;
            this.Entity = this.Negocio.getById(this.Entity);
            this.beginEdit(true);
        }

        private void create()
        {
            this.Entity = new Z();
            this.beginEdit(false);
        }

        protected override void doFilter() 
        {
            try {
                Z EntityFilter = this.getFilter();
                this.setList(getFilteredObjectList(EntityFilter));
            }
            catch (NegocioException ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (DatosException ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (Exception)
            {
                MessageBox.Show("Error inesperado. Ponganse en contacto con el administrador del sistema ", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }        

        protected virtual List<Z> getFilteredObjectList(Z filter){
            return this.Negocio.getAll(filter);
        }

        protected virtual void BaseListado_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.Hide();
        }

        private void DgList_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex < 0 || e.ColumnIndex < 0)
                return;
            int id = Convert.ToInt32(this.DgList["Id", e.RowIndex].Value);
            if (e.ColumnIndex == DgList.Columns[this.SELECCIONAR].Index)
            {
                if (this.isSearchForm)
                    this.select(id);
                else
                    this.edit(id);
            }
            else if (!this.isSearchForm && e.ColumnIndex == DgList.Columns[this.BORRAR].Index)
            {
                this.delete(id);                
            }
        }

        private void select(int id)
        {
            this.Entity.Id = id;
            this.Entity = this.Negocio.getById(this.Entity);
            this.DialogResult = DialogResult.OK;
            this.Hide();
        }

        private void btNew_Click(object sender, EventArgs e)
        {
            this.create();
        }

        private void tsFiltrar_Click(object sender, EventArgs e)
        {
            this.filter();
        }

        private void tsLimpiar_Click(object sender, EventArgs e)
        {
            this.limpiar();
        }

        protected void hideFilters() {
            this.tsFiltrar.Visible = false;
            this.tsLimpiar.Visible = false;
        }

        protected virtual void limpiar() { this.filter(); }
    }
}
